package drds.configuration.db.table_mapping;

import lombok.extern.slf4j.Slf4j;

import javax.sql.DataSource;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

/**
 * 本类记录表字段名及其类型
 */
@Slf4j
public class TableInfo {
    public static final String TRUE = "TRUE";//需要check
    public static final String FALSE = "FALSE";//不需要check
    //注解列映射关系维护
    public Map<String, java.lang.reflect.Field> fieldColumnNameToFieldMap = new HashMap<String, java.lang.reflect.Field>();
    public Map<java.lang.reflect.Field, String> fieldToFieldColumnNameMap = new HashMap<java.lang.reflect.Field, String>();
    public Map<String, Class<?>> fieldColumnNameToClassTypeMap = new HashMap<String, Class<?>>();
    //数据库中列类型
    public Map<String, Class<?>> columnNameToClassTypeMap = new HashMap<String, Class<?>>();
    //
    private String dataSourceId;
    private DataSource masterDataSource;
    private String tableName;
    private String primaryKey;
    private boolean checkBaseColumn = false;
    //
    private Class<? extends Model<?>> modelClass;

    //
    public TableInfo() {
    }


    /**
     * 默认值是ID
     */
    public TableInfo(String dataSourceId, DataSource masterDataSource, String tableName, Class<? extends Model<?>> modelClass) {
        this(dataSourceId, masterDataSource, tableName, "id", modelClass);
    }

    // 构造方法
    public TableInfo(String dataSourceId, DataSource masterDataSource, String tableName, String primaryKey, Class<? extends Model<?>> modelClass) {
        if (dataSourceId == null || "".equals(dataSourceId.trim())) {
            throw new NullPointerException("groupDataSourceId为空");
        }
        if (masterDataSource == null) {
            throw new NullPointerException("dataSource为空");
        }
        if (tableName == null || "".equals(tableName.trim())) {
            throw new NullPointerException("表名为空");
        }
        if (primaryKey == null || "".equals(primaryKey.trim())) {
            throw new NullPointerException("主键为空");
        }
        if (modelClass == null) {
            throw new NullPointerException("Model类为空");
        }
        this.dataSourceId = dataSourceId;
        this.masterDataSource = masterDataSource;
        //
        this.tableName = tableName.trim();
        this.primaryKey = primaryKey.trim();
        this.modelClass = modelClass;
        //字段映射
        columnNameMapping(modelClass, this);
    }

    /**
     * 列名映射
     *
     * @param modelClass
     * @param tableInfo
     */
    public void columnNameMapping(Class<? extends Model<?>> modelClass, TableInfo tableInfo) {
        log.debug("读取modelClass的私有属性");
        List<java.lang.reflect.Field> declaredFieldList = new ArrayList<java.lang.reflect.Field>();
        List<String> declaredFieldColumnNameList = new ArrayList<String>();//字段列
        //同时需要记录字段类型
        java.lang.reflect.Field[] declaredFields = modelClass.getDeclaredFields();
        for (java.lang.reflect.Field field : declaredFields) {
            // 要求属性必须是private
            if (Modifier.isPrivate(field.getModifiers())) {
                field.setAccessible(true);//在这统一进行初始化
                Field column = field.getAnnotation(Field.class);
                if (column != null) {
                    declaredFieldColumnNameList.add(column.withColumnName());
                    declaredFieldList.add(field);
                    //
                    tableInfo.fieldColumnNameToFieldMap.put(column.withColumnName(), field);
                    tableInfo.fieldColumnNameToClassTypeMap.put(column.withColumnName(), field.getType());
                    //
                    tableInfo.fieldToFieldColumnNameMap.put(field, column.withColumnName());
                }
            }
        }
        //
        log.debug("读取modelClass的静态属性");
        //
        List<java.lang.reflect.Field> fieldList = new ArrayList<java.lang.reflect.Field>();
        List<String> fieldColumnNameList = new ArrayList<String>();
        // public
        java.lang.reflect.Field[] fields = modelClass.getFields();
        for (java.lang.reflect.Field field : fields) {
            ColumnName columnName = field.getAnnotation(ColumnName.class);
            if (columnName != null) {
                field.setAccessible(true);//略过
                String name = null;
                try {
                    name = field.get(null).toString();
                } catch (IllegalAccessException e) {
                    throw new RuntimeException(e);
                }
                fieldColumnNameList.add(name);
                fieldList.add(field);
            }
        }
        // 要求列必须在static中找到
        for (String declaredFieldName : declaredFieldColumnNameList) {
            boolean find = false;
            for (String fieldName : fieldColumnNameList) {
                if (fieldName.equals(declaredFieldName)) {
                    find = true;
                    break;
                }
            }
            if (!find) {
                String msg = "在" + modelClass.getName() + "中,缺少私有属性对应的静态表字段列名" + declaredFieldName;
                log.error(msg);
                throw new RuntimeException(msg);
            }
        }

        //需要和数据库里面的表结构进行比对
    }

    public String getDataSourceId() {
        return dataSourceId;
    }

    //
    public void setDataSourceId(String dataSourceId) {
        this.dataSourceId = dataSourceId;
    }

    /**
     * 如果是更新操作则直接使用主数据库
     */
    public DataSource getMasterDataSource() {
        return masterDataSource;
    }

    //
    public void setMasterDataSource(DataSource masterDataSource) {
        this.masterDataSource = masterDataSource;
    }

    //
    public String getTableName() {
        return tableName;
    }

    public String getPrimaryKey() {
        return primaryKey;
    }

    public Class<? extends Model<?>> getModelClass() {
        return modelClass;
    }

    //

    /**
     * 添加字段信息
     */
    public void addColumnInfo(String columnName, Class<?> columnType) {
        if (columnNameToClassTypeMap.containsKey(columnName)) {
            throw new IllegalArgumentException("属性:" + columnName + "重复");
        }
        columnNameToClassTypeMap.put(columnName, columnType);
    }

    public Map<String, Class<?>> getColumnNameToClassTypeMap() {
        return columnNameToClassTypeMap;
    }

    public boolean containsColumnName(String columnLabel) {
        return columnNameToClassTypeMap.containsKey(columnLabel);
    }

    public Class<?> getColumnType(String columnName) {
        return columnNameToClassTypeMap.get(columnName);
    }


    public void printColumnMapInfo() {
        if (columnNameToClassTypeMap != null && columnNameToClassTypeMap.size() != 0) {
            log.info("打印字段类型");
            for (Entry<String, Class<?>> entry : columnNameToClassTypeMap.entrySet()) {
                String key = entry.getKey();
                Class clazz = entry.getValue();
                log.info(("key:" + key + "类型" + clazz.getName()));
            }
        }
    }

    //
    public boolean isCheckBaseColumn() {
        return checkBaseColumn;
    }

    public void setCheckBaseColumn(boolean checkBaseColumn) {
        this.checkBaseColumn = checkBaseColumn;
    }

}
